package com.example.service.webhook.filter;


import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.security.RolesAllowed;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;

/**
 * 访问权限控制
 */
public class AuthInterceptor extends HandlerInterceptorAdapter {
    private static final Logger LOGGER = LoggerFactory.getLogger(AuthInterceptor.class);

    private String webHookToken;

    public AuthInterceptor(String webHookToken) {
        this.webHookToken = webHookToken;
    }

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        HandlerMethod hm = (HandlerMethod) handler;
        Method method = hm.getMethod();
        if (method.getDeclaringClass().isAnnotationPresent(RestController.class) && method.isAnnotationPresent(RolesAllowed.class)) {
            String[] rolesAllowed = method.getAnnotation(RolesAllowed.class).value();
            return isAccessAllowed(Arrays.asList(rolesAllowed), httpServletRequest, httpServletResponse);
        }
        return true;
    }

    private boolean isAccessAllowed(Collection<String> rolesAllowed, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        for (String role : rolesAllowed) {
            if (role.equals("user")) {
                //TODO: authenticate the token from http header, return true if allowed
                return true;
            } else if (role.equals("moxie")) {
                String authorization = httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION);
                if (authorization != null) {
                    String accessToken = getAccessToken(authorization);
                    if (accessToken != null && accessToken.equals(webHookToken)) {
                        return true;
                    }
                }
            } else {
                LOGGER.error("unknown role annotation:{}", role);
            }
        }
        try {
            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "unauthorized request");
        } catch (IOException e) {
        }
        return false;
    }

    private String getAccessToken(String authorization) {
        Preconditions.checkNotNull(authorization);
        int i = authorization.indexOf(' ');
        return i > 0 ? authorization.substring(i + 1).trim() : null;
    }
}
